
import { Layout, Drawer, Affix, Button, Row, Col, Tag, message } from 'antd';
import { ShoppingCartOutlined, LoadingOutlined, FallOutlined, RiseOutlined, WarningOutlined, ReloadOutlined } from '@ant-design/icons';
import React from 'react';
import { Cart } from 'components/Cart';
import { getProducts } from 'services/products';
import { Products } from 'components/Products';
import { Skeleton } from 'components/Products/Skeleton';
import { ProductSizes } from 'components/ProductSizes';
import { ESort, ICartProduct, ICartTotal, IProduct, IProductFilter, IProductWithSelected, IReqCancel } from 'models';
import { CartLocalStorage } from 'local/CartLocalStorage';
const { Sider, Content } = Layout;

const allSizes = ["X", "L", "XL", "XXL"];
interface IState {
  cartOpen: boolean;
  products: IProduct[];
  productFilter: IProductFilter;
  productsLoading: boolean;
  productLoadErrMsg: string | null;
}
export class App extends React.Component<any, IState> {
  private pageSize = 30;
  constructor(props: any) {
    super(props);
    this.state = {
      cartOpen: false,
      productFilter: {},
      products: [],
      productsLoading: false,
      productLoadErrMsg: null,
    };
  }

  async componentDidMount(): Promise<void> {
    await this.loadProduct(this.state.productFilter, 1, true);
  }

  loadProductsToken: IReqCancel | null = null;

  onCloseCart = () => {
    this.setState({
      cartOpen: false,
    });
  }

  openCart = () => {
    this.setState({
      cartOpen: true,
    });
  }

  async reload() {
    await this.loadProduct(this.state.productFilter, 1, true);
  }

  async loadProduct(productFilter: IProductFilter, pageNum: number, reset: boolean) {
    if (this.loadProductsToken) {
      //前一个还在请求,取消掉
      this.loadProductsToken.cancel();
      this.loadProductsToken = null;
    }
    this.setState({
      productsLoading: true,
      productFilter: productFilter,
      productLoadErrMsg: null,
    });

    //创建异步任务
    const productsAsync = getProducts(productFilter, this.pageSize, pageNum);
    this.loadProductsToken = productsAsync.cancelToken;
    //等待任务完成
    const productsRet = await productsAsync.task;
    if (!productsRet.success) {
      this.setState({
        productsLoading: false,
        productLoadErrMsg: `[${productsRet.code}] ${productsRet.error}`,
      });
      return console.error('产品加载失败:', productsRet);
    }
    this.setState({
      products: reset ? productsRet.data.products : [...this.state.products, ...productsRet.data.products],
      productsLoading: false,
    });
  }

  onFilter = async (selectedSizes: string[]) => {
    await this.loadProduct({ ...this.state.productFilter, sizes: [...selectedSizes] }, 1, true);
  }

  async onSort(propName: string) {
    const { productFilter } = this.state;
    let sortProp: string | undefined = propName;
    let sort = productFilter.sort;
    productFilter.sortProp = propName;
    //排序三种状态切换
    if (!sort) sort = ESort.Asc;
    else if (sort === ESort.Asc) sort = ESort.Desc;
    else sort = undefined;
    if (!sort) sortProp = undefined;

    await this.loadProduct({ ...this.state.productFilter, sort, sortProp }, 1, true);
  }

  onAddProductToCart = (product: IProductWithSelected) => {
    CartLocalStorage.addProduct(product);
    this.openCart();
  }
  onCheckout = (products: ICartProduct[], total: ICartTotal) => {
    message.info('剩下就是订单的流程了~');
    //一般这里要等提交订单成功后回来,再清空购物车
    CartLocalStorage.clearProducts();
    this.onCloseCart();
  }

  render() {
    const { cartOpen, products, productFilter, productsLoading, productLoadErrMsg } = this.state;
    return (
      <>
        <div className="rootWrap">
          <Layout className='contentWrap'>
            <Sider breakpoint="lg" theme="light">
              <Affix offsetTop={20}>
                <div className='leftSearchBar'>
                  <Row gutter={[10, 10]} justify="center" wrap={true} style={{ padding: '5%' }}>
                    <Col span={24}>
                      <Tag>Sizes:</Tag>
                    </Col>
                    <ProductSizes multiple={true} sizes={allSizes} onFilter={this.onFilter}
                      colProps={{ md: 24, lg: 5, xl: 5 }} />
                    <Col span={24}>
                      <Button onClick={() => this.onSort('price')}>价格
                        {productFilter.sort === ESort.Asc && <RiseOutlined />}
                        {productFilter.sort === ESort.Desc && <FallOutlined />}
                      </Button>
                    </Col>
                  </Row>
                  {productsLoading && <div style={{ textAlign: 'center' }}><LoadingOutlined /></div>}
                  {!!productLoadErrMsg && (
                    <div style={{ textAlign: 'center' }}>
                      <div><WarningOutlined />{productLoadErrMsg}</div>
                      <ReloadOutlined onClick={() => this.reload()} />
                    </div>
                  )}
                </div>
              </Affix>

            </Sider>
            <Layout>
              <Content style={{ padding: '2%' }}>
                <div className='cartWrap'>
                  <Row className='cartWrapRow' gutter={[32, 32]} justify="center" wrap={true} >
                    {productsLoading || (products.length <= 0) ? (
                      <Skeleton size={this.pageSize} />
                    ) : (
                      <Products productFilter={productFilter} list={products} addProductToCart={this.onAddProductToCart} />
                    )}
                  </Row>
                </div>
              </Content>
            </Layout>
          </Layout>
          <Button className='cartBtn' onClick={this.openCart}>
            <ShoppingCartOutlined className="cartBtn" />
          </Button>
          <Drawer title="购物车" width="60%" placement="right" onClose={this.onCloseCart} open={cartOpen}>
            <Cart openTS={cartOpen ? Date.now() : 0} onCheckout={this.onCheckout} />
          </Drawer>
          {productsLoading && (
            <div className='productLoading'>
              <LoadingOutlined className='bigCenter' />
            </div>
          )}
        </div>
      </>
    );
  }
}

export default App;
